/****************************************************************************
 *                                                                          *
 * Copyright (c) 2009 Nuvoton Technology Corp. All rights reserved.         *
 *                                                                          *
 ****************************************************************************/

/****************************************************************************
 *
 * FILENAME
 *     rtc.c
 *
 * DESCRIPTION
 *
 *
 **************************************************************************/

#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <linux/sysctl.h>
#include "rtc_lib.h"


struct rtc_time rtc_tm;
struct rtc_time rtc_alarm;

void (*alarm_function)() = NULL;
void (*tick_function)() = NULL;

int scale_type = HR24;
int main_pid;

int fd;
int irq;//alarm or tick


void dis_alarm()
{
		int ret;
		
		if(fd)
		{
				ret = ioctl(fd, RTC_AIE_OFF, 0);	
				alarm_function = NULL;
		}
		return ;
}

void dis_tick()
{
	int ret = -1;
	int tick = 0;
	
	if(fd)
	{	
			ret = ioctl(fd,RTC_TICK_OFF,0);
			ret = ioctl(fd,RTC_TICK_SET,&tick);
			ret = ioctl(fd,RTC_CALLBACK,0);		
			tick_function = NULL;
	}
	
	return ;
}


void get_alarm_time(struct rtc_time *tm)
{
		int ret = -1;
		
		if(fd){
			
		 	ret=ioctl(fd,RTC_ALM_READ,&rtc_alarm);
		 	
		 	tm->tm_year = rtc_alarm.tm_year;
		 	tm->tm_mon = rtc_alarm.tm_mon;
		 	tm->tm_mday = rtc_alarm.tm_mday;
		 	tm->tm_hour = rtc_alarm.tm_hour;
		 	tm->tm_min = rtc_alarm.tm_min;
		 	tm->tm_sec = rtc_alarm.tm_sec;
		 	
		 	printf("alarm_time is: %04d-%02d-%02d %02d:%02d:%02d\n",rtc_alarm.tm_year,rtc_alarm.tm_mon,rtc_alarm.tm_mday,rtc_alarm.tm_hour,rtc_alarm.tm_min,rtc_alarm.tm_sec);
		}
		 
		return ;
		
}


int get_tick_count()
{
	int ret = -1;
	
	ioctl(fd,RTC_TICK_READ,&ret);
	return ret;
}


//void get_time(struct rtc_time *tm)
void get_time(unsigned char * data)
{
		int ret = -1;
		int tmp = 0;
		if(fd){
		 	ret=ioctl(fd,RTC_RD_TIME,&rtc_tm);
		 	
		 	if(scale_type == HR12)
		 	{
		 		
		 		if(rtc_tm.tm_hour>20)
		 			rtc_tm.tm_hour -= 20;
		 	}
			tmp = rtc_tm.tm_year - 2000;
			data[0] = (unsigned char)( (tmp - tmp % 10) * 16 / 10 + tmp % 10 );
			tmp = rtc_tm.tm_mon;
			data[1] = (unsigned char)( (tmp - tmp % 10) * 16 / 10 + tmp % 10 );
			tmp = rtc_tm.tm_mday;
			data[2] = (unsigned char)( (tmp - tmp % 10) * 16 / 10 + tmp % 10 );
			tmp = rtc_tm.tm_hour;
			data[3] = (unsigned char)( (tmp - tmp % 10) * 16 / 10 + tmp % 10 );
			tmp = rtc_tm.tm_min;
			data[4] = (unsigned char)( (tmp - tmp % 10) * 16 / 10 + tmp % 10 );
			tmp = rtc_tm.tm_sec;
			data[5] = (unsigned char)( (tmp - tmp % 10) * 16 / 10 + tmp % 10 );
			/*
		 	tm->tm_year = rtc_tm.tm_year;
		 	tm->tm_mon = rtc_tm.tm_mon;
		 	tm->tm_mday = rtc_tm.tm_mday;
		 	tm->tm_hour = rtc_tm.tm_hour;
		 	tm->tm_min = rtc_tm.tm_min;
		 	tm->tm_sec = rtc_tm.tm_sec;
			*/
			//printf("%04d/%02d/%02d %02d:%02d:%02d\n",rtc_tm.tm_year,rtc_tm.tm_mon,rtc_tm.tm_mday,rtc_tm.tm_hour,rtc_tm.tm_min,rtc_tm.tm_sec);
	
		}
		
		return ;
		
}



void call_back(int irqflag)
{
	irq = irqflag;
	kill(main_pid,SIGRTC);
}

void set_alarm(unsigned int year,unsigned int month,unsigned int day,unsigned int hour,unsigned int min,unsigned int sec,void(*func)())
{
			int ret = -1;
			
			rtc_alarm.tm_year = year;
			rtc_alarm.tm_mon = month;
			rtc_alarm.tm_mday = day;
			rtc_alarm.tm_hour = hour;
			rtc_alarm.tm_min = min;
			rtc_alarm.tm_sec = sec;
			
			if (fd)
			{
				ret = ioctl(fd, RTC_AIE_ON, 0);	
				
				//ret = ioctl(fd,RTC_CALLBACK, call_back);	
				alarm_function = func;	
				ret = ioctl(fd, RTC_ALM_SET, &rtc_alarm);
				
				
				printf("Set ALARM OK!\n");
				
			}
			
			return ;
			
}


void set_tick(unsigned int tick,void(*func)())
{
		int ret = -1;
		
		if(fd)
		{
			ret = ioctl(fd,RTC_TICK_ON,0);
			
			//ret = ioctl(fd,RTC_CALLBACK,call_back);
			tick_function = func;
			ret = ioctl(fd,RTC_TICK_SET,&tick);
			
		}
		
		return ;
}


//void set_time(unsigned int year,unsigned int mouth,unsigned int day,unsigned int hour,unsigned int min,unsigned int sec)

void set_time(unsigned int * data)
{
			int ret = -1;
			
			rtc_tm.tm_year = data[0]; // year-2000;
			rtc_tm.tm_mon = data[1]; //mouth;
			rtc_tm.tm_mday = data[2]; //day;
			rtc_tm.tm_hour = data[3]; //hour;
			rtc_tm.tm_min =  data[4]; //min;
			rtc_tm.tm_sec =  data[5]; //sec;
			

			if (fd)
			{
				ret = ioctl(fd, RTC_SET_TIME, &rtc_tm);
				//printf("Set RTC OK!\n");
			}
			else printf("Set RTC failed!\n");
			return ;		
}


void time_scale(int scale)
{
	int ret = -1;
	
	if(fd)
	{
		ret = ioctl(fd, RTC_TIME_SCALE, &scale);
		scale_type = scale;
	}
	
	return ;
}


void mySignalHandler (int sig)
{
   switch (sig){
    case SIGTERM: 

    case SIGINT:
      dis_tick();
      dis_alarm();
      exit(0);

    break;
      
    case SIGRTC:
    	if(irq & ALARM_IRQ){
    		if(alarm_function != NULL)
    			alarm_function();
    	}
    	if(irq & TICK_IRQ){
    		if(tick_function != NULL)
    			tick_function();
    	}
    		
    break;
    
    default:
      printf ("What?\n");
   }
}

int get_scale_type()
{
	return scale_type;
}

int open_rtc(int pid)
{

	fd = open("/dev/rtc", O_RDWR);
	if (fd == -1)
	{
		printf("Can't open device rtc!\n");
		return -1;
	}
	
	main_pid = pid;
	
	
	signal (SIGTERM, mySignalHandler); /* for the TERM signal.. */

  	signal (SIGINT, mySignalHandler); /* for the CTRL+C signal.. */

	signal (SIGRTC, mySignalHandler);
	
	ioctl(fd, RTC_TIME_SCALE, &scale_type);
	
	ioctl(fd,RTC_CALLBACK,call_back);
	
	return 0;
}
